import { getData, setData, data } from './dataStore';
import fs from 'fs';
import { QuizList, Error, QuizId, Success } from './interface';
import { isValidToken } from './check';

function loadTrashData() {
    const trashPath = './trash.json';

    if (fs.existsSync(trashPath)) {
        const fileContent = fs.readFileSync(trashPath, { encoding: 'utf8' });

        const trashData = JSON.parse(fileContent);

        return trashData;
    } else {
        return [];
    }
}

export function adminQuizList(token: string): QuizList | Error {
    const data = getData();

    const authUserId = isValidToken(token);
    if (!authUserId) {
        return { error: 'Token is empty or invalid (does not refer to valid logged in user session)' };
    }

    let Targeted_quizzes = data.quizzes.filter(quiz => quiz.AuthorID.includes(authUserId));

    if (Targeted_quizzes.length === 0) {
        return { quizzes: [] };
    }


    let result = Targeted_quizzes.map(quiz => {
        return {
            quizId: quiz.QuizID,
            name: quiz.Name
        };
    });

    return { quizzes: result };
}


export function adminQuizNameUpdate(token: string, quizId: number, newName: string): Success | Error {
    const data = getData();
    const authUserId = isValidToken(token);
    if (!authUserId) {
        return { error: 'Token is empty or invalid (does not refer to valid logged in user session)' };
    }

    const { users, quizzes } = data;


    if (!users.some(user => user.userID === authUserId)) {
        return { error: 'AuthUserId is not a valid user.' };
    }

    const quiz = quizzes.find(quiz => quiz.QuizID === quizId);
    if (!quiz) {
        return { error: 'Quiz ID does not refer to a valid quiz.' };
    }


    if (!quiz.AuthorID.includes(authUserId)) {
        return { error: 'Quiz ID does not refer to a quiz that this user owns.' };
    }

    if (!/^[a-zA-Z0-9 _ ]+$/.test(newName)) {
        return { error: 'Name contains invalid characters. Valid characters are alphanumeric and spaces.' };
    }


    if (newName.length < 3 || newName.length > 30) {
        return { error: 'Name must be between 3 and 30 characters long.' };
    }

    if (quizzes.some(otherQuiz => otherQuiz.Name === newName && otherQuiz.QuizID !== quizId)) {
        return { error: 'Name is already used by the current logged in user for another quiz.' };
    }

    quiz.Name = newName;

    setData(data);

    return { message: 'Success!' };
}

export function adminQuizDescriptionUpdate(authUserId: number, quizId: number, description: string): Success | Error {

    const dataStore = getData();

    const { users, quizzes } = dataStore;
    if (description.length > 100) {
        return { error: 'Description is more than 100 characters in length.' };
    }

    if (!users.some(user => user.userID === authUserId)) {
        return { error: 'AuthUserId is not a valid user.' };
    }

    const quiz = quizzes.find(quiz => quiz.QuizID === quizId);
    if (!quiz) {
        return { error: 'Quiz ID does not refer to a valid quiz.' };
    }

    if (!quiz.AuthorID.includes(authUserId)) {
        return { error: 'Quiz ID does not refer to a quiz that this user owns.' };
    }

    quiz.Description = description;
    setData(dataStore);

    return { message: 'Success!' };
}

export function adminQuizCreate(token: string, name: string, description: string): QuizId | Error {
    const data = getData();

    const authUserId = isValidToken(token);
    if (!authUserId) {
        return { error: 'Token is empty or invalid (does not refer to valid logged in user session)' };
    }

    if (name.length > 30 || name.length < 3) {
        return { error: 'Name is either less than 3 characters long or more than 30 characters long.' };
    }

    let isNameExists = data.quizzes.some(quiz => quiz.Name.includes(name));
    if (isNameExists) {
        return { error: 'Name is either less than 3 characters long or more than 30 characters long.' };
    }

    if (description.length > 100) {
        return { error: 'Description is more than 100 characters in length (note: empty strings are OK).' };
    }

    if (/[^a-zA-Z0-9 ]+/.test(name)) {
        return { error: 'Name contains invalid characters. Valid characters are alphanumeric and spaces.' };
    }

    const TimeCreated = new Date();
    let TimeLastEdited = new Date();
    const quizId = data.quizzes.length + 1;

    data.quizzes.push({
        QuizID: quizId,
        AuthorID: [authUserId],
        Name: name,
        TimeCreated: TimeCreated,
        TimeLastEdited: TimeLastEdited,
        Description: description,
        State: 'ACTIVE',
        Questions: undefined,
        timeLastEdited: undefined,
        Sessions: undefined,
    });

    setData(data);

    return {
        quizId: quizId
    };
}

function sendQuizToTrash(quizIndex: number) {
    const trashPath = './trash.json';
    let trashData = fs.existsSync(trashPath) ? JSON.parse(fs.readFileSync(trashPath, { encoding: 'utf8' })) : [];
    const [quizToTrash] = data.quizzes.splice(quizIndex, 1);
    trashData.push(quizToTrash);
    fs.writeFileSync(trashPath, JSON.stringify(trashData, null, 2));
}

export function adminQuizRemove(token: string, quizId: number): Success | Error {
    let data = getData();

    const authUserId = isValidToken(token);
    if (!authUserId) {
        return { error: 'Token is empty or invalid (does not refer to valid logged in user session)' };
    }

    const userExists = data.users.some(user => user.userID === authUserId);
    if (!userExists) {
        return { error: 'authUserId is not a valid user.' };
    }

    const quizIndex = data.quizzes.findIndex(quiz => quiz.QuizID === quizId);
    if (quizIndex === -1) {
        return { error: 'Quiz ID does not refer to a valid quiz.' };
    }

    const foundQuiz = data.quizzes[quizIndex];
    if (!foundQuiz.AuthorID.includes(authUserId)) {
        return { error: 'Quiz ID does not refer to a quiz that this user owns.' };
    }

    sendQuizToTrash(quizIndex);
    setData(data);

    return { message: 'Quiz removed successfully.' };
}


export function adminQuizInfo(token: string, quizId: number) {
    const dataStore = getData();
    const authUserId = isValidToken(token);
    if (!authUserId) {
        return { error: 'Token is empty or invalid (does not refer to valid logged in user session)' };
    }

    const user = dataStore.users.find(user => user.userID === authUserId);

    if (user) {

        const quiz = dataStore.quizzes.find(quiz => quiz.QuizID === quizId);

        if (quiz) {

            if (quiz.AuthorID.includes(authUserId)) {

                return {

                    quizId: quiz.QuizID,
                    name: quiz.Name,
                    timeCreated: quiz.TimeCreated,
                    timeLastEdited: quiz.TimeLastEdited,
                    description: quiz.Description,

                };

            } else {

                return { error: 'Quiz ID does not refer to a quiz that this user owns.' };

            }
        } else {

            return { error: 'Quiz ID does not refer to a valid quiz.' };

        }
    } else {

        return { error: 'AuthUserId is not a valid user.' };

    }
}

export function adminTrashView(token: string) {
    const authUserId = isValidToken(token);
    if (!authUserId) {
        return { error: 'Token is empty or invalid (does not refer to valid logged in user session)' };
    }
    const trashData = loadTrashData();

    const filteredTrashData = trashData.filter((item: { userId: number; }) => {
        return item.userId === authUserId;
    });

    return {
        quizId: filteredTrashData.QuizID,
        name: filteredTrashData.Name
    };

}

export function adminTrashRestore(token: string, quizId: number) {
    const trashData = loadTrashData();
    const authUserId = isValidToken(token);
    const dataStore = getData();
    if (!authUserId) {
        return { error: 'Token is empty or invalid (does not refer to valid logged in user session)' };
    }

    let foundItem = trashData.find((item: { userID: number; QuizID: number[]; }) =>
        item.userID === authUserId && item.QuizID.includes(quizId)
    );

    let containsName = dataStore.quizzes.some(quiz => quiz.Name === foundItem.name);
    let containsQuizID = dataStore.quizzes.some(quiz => quiz.QuizID === quizId);

    if (containsName === true) {
        return { error: 'Quiz name of the restored quiz is already used by another active quiz' };
    }
    if (containsQuizID === true) {
        return { error: 'Quiz Id of the restored quiz is already used by another active quiz' };
    }

    data.quizzes.push(foundItem);

    return {};

}